/**
 * Take neighbours and make predictions as in 
 * Bell, Koren (2007). Improved Neighbourhood-based Collaborative Filtering
 * (kdd-2007-cf-workshop on their website)
 *
 * Usage:
 * ... Ahat_file <neighbours
 *
 * Ahat_file: output from bellkor_Ahat
 * neighbours: output from bellkor_knn
 *
 * Output format is:
 * movie_id user_id rating
 * movie_id user_id rating
 * ...
 */
#include <fstream>
#include <iostream>
#include <iterator>
#include "u1.h"
#include "io.h"
#include "symmetric_matrix.h"

using namespace std;

int main(int argc, char **argv)
{
  if (argc != 2) {
    TRACE<<"see comments for usage"<<endl;
    exit(EXIT_FAILURE);
  }

  string Ahat_file = argv[1];

  // Read Ahat matrix from binary file.
  TRACE<<"loading Ahat from "<<Ahat_file<<endl;
  symmetric_matrix<float> Ahat(NUM_MOVIES);
  ifstream Ahat_is(Ahat_file.c_str());
  Ahat.read_binary(Ahat_is);
  Ahat_is.close();

  // A, b and w are as in the paper. N is the set of neighbours.
  symmetric_matrix<float> A(1);
  vector<float> b, w;
  vector<id_rating_t<float> > N;

  // Read neighbours.
  int movie_id, user_id;
  size_t K;
  while(cin>>movie_id>>user_id>>K) {
    // Read neighbours.
    N.clear();
    for (size_t k = 0; k < K; ++k) {
      id_rating_t<float> n;
      if (!(cin>>n)) {
        TRACE<<"unexpected neighbour format; user "<<user_id<<" movie "
          <<movie_id<<" neighbour "<<k<<endl;
        exit(EXIT_FAILURE);
      }
      N.push_back(n);
    }

    // Build A from Ahat for the neighbours N. A is symmetric.
    A.resize(K);
    for (size_t j = 0; j < K; ++j) {
      for (size_t k = j; k < K; ++k) {
        A(j,k) = Ahat(N[j].id-1, N[k].id-1);
      }
    }

    // Build b from Ahat for neighbours N.
    b.clear();
    for (size_t j = 0; j < K; ++j) {
      b.push_back(Ahat(N[j].id-1, movie_id-1));
    }

    // Solve for weights.
    nonnegative_quadratic_opt<float>(A, b, 1e-4, 100, w);

    // Compute rating from weights.
    float rating = 0;
    for (size_t j = 0; j < K; ++j) {
      rating += w[j]*N[j].rating;
    }

    // Output.
    cout<<movie_id<<','<<user_id<<','<<rating<<'\n';
  }

  return EXIT_SUCCESS;
}
/*
* Copyright (c) 2009 John Lees-Miller
* 
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
* 
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

